home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-02 | 49.6 KB | 2,273 lines |
- Newsgroups: comp.sources.misc
- subject: v13i019: PD make V1.6 (Part 2 of 2)
- From: greggy@zebra.UUCP (Greg Yachuk)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 13, Issue 19
- Submitted-by: greggy@zebra.UUCP (Greg Yachuk)
- Archive-name: make1.6/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of archive 2 (of 2)."
- # Contents: build.c default.mk default.msc make.h makefile
- # makefile.msc parse.c tstring.c tstring.h
- # Wrapped by greggy@etude on Thu May 31 10:55:31 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'build.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'build.c'\"
- else
- echo shar: Extracting \"'build.c'\" \(7577 characters\)
- sed "s/^X//" >'build.c' <<'END_OF_FILE'
- X/*
- X * build.c An imitation of the Unix MAKE facility
- X *
- X * 88-10-01 v1.0 created by greg yachuk, placed in the public domain
- X * 88-10-06 v1.1 changed prerequisite list handling
- X * 88-11-11 v1.2 fixed some bugs and added environment variables
- X * 89-07-12 v1.3 stop appending shell commands, and flush output
- X * 89-08-01 v1.4 AB lots of new options and code
- X * 89-10-30 v1.5 -f -S -q options, took some changes from v1.4
- X * 90-04-18 v1.6 -b -- -W options, emulate <<, non-BSD cleanup
- X */
- X
- X#include <stdio.h>
- X#include <string.h>
- X#ifdef MSDOS
- X#include <stdlib.h>
- X#include <process.h>
- X#endif
- X#ifdef BSD
- X#include <sys/wait.h>
- X#endif
- X
- X#include "make.h"
- X#include "tstring.h"
- X#include "decl.h"
- X
- X#ifndef MSDOS
- Xchar **bsearch();
- X#endif
- X
- Xchar *tmpfn = NULL;
- X#define shellunlink() if(tmpfn!=NULL)unlink(tmpfn),tfree(tmpfn),tmpfn=NULL
- X
- X/*
- X * shell_cmpr - comparison routine for "shell command" binary search.
- X */
- Xshell_cmpr(key, list)
- Xchar *key;
- Xchar **list;
- X{
- X return (strcmp(key, *list));
- X}
- X
- X/*
- X * build - process the shell commands
- X */
- Xbuild(shellp)
- Xshellptr *shellp;
- X{
- X char **argv; /* argified version of scmd */
- X int runst; /* exec return status */
- X char *scmd; /* command with symbols broken out */
- X char *tcmd; /* copy of scmd for `tokenize' */
- X char *errnum; /* error number in ascii */
- X char *errmsg; /* error message */
- X int i;
- X char *sp;
- X char *tp;
- X char **shcp; /* pointer to shell command list */
- X
- X if (shellp == NULL || opts.query)
- X return (0);
- X
- X /* process every shell line */
- X
- X for (; *shellp != NULL;
- X tfree(scmd), tfree(tcmd), tfree(argv), ++shellp)
- X {
- X /* breakout runtime symbols (e.g. $* $@ $<) */
- X scmd = breakout((*shellp)->scmd);
- X
- X /* make a copy because tokenize litters '\0's */
- X tcmd = tstrcpy(scmd);
- X argv = tokenize(tcmd);
- X
- X for (tp = scmd, i = 0; argv[i]; i++)
- X {
- X /* pretend to handle inline input ("<<" operator) */
- X while ((sp = strchr(argv[i], '<')) != NULL)
- X {
- X if (*++sp != '<')
- X continue;
- X
- X sp[-1] = '\0';
- X
- X /* got "<<". collect commands into a file */
- X if (*++sp != '\0') /* got "<<TAG" */
- X sp = shellinput(&shellp, sp);
- X else
- X {
- X /* got "<< TAG" (note space before TAG) */
- X sp = shellinput(&shellp, argv[i + 1]);
- X if (argv[i + 1])
- X {
- X tfree(argv[i + 1]);
- X argv[i + 1] = tstrcpy("");
- X }
- X }
- X
- X /* add the filename to the argument */
- X sp = tstrcat(argv[i], sp);
- X tfree(argv[i]);
- X argv[i] = sp;
- X }
- X
- X /* now strip the quotes from the argument */
- X strcpy(tp, tunquote(argv[i]));
- X while (*tp++);
- X tp[-1] = ' ';
- X }
- X
- X /* finally, terminate the command line (scmd) */
- X tp[-1] = '\0';
- X
- X if (!opts.silent && (opts.noexec || !(*shellp)->s_silent))
- X {
- X puts(scmd);
- X fflush(stdout);
- X }
- X
- X /* look for $(MAKE) */
- X if (equal(argv[0], opts.make))
- X {
- X /* call ourselves recursively */
- X new_make(argv);
- X continue;
- X }
- X
- X if (opts.noexec)
- X continue;
- X
- X /* any SHELL meta-characters MUST be handled by the shell */
- X if (!(*shellp)->s_shell && strpbrk(scmd, SHELL_METAS))
- X (*shellp)->s_shell = 1;
- X
- X if (shell_cmds && !(*shellp)->s_shell)
- X {
- X /* check for COMMAND.COM builtin commands */
- X for (shcp = shell_cmds; *shcp; ++shcp);
- X shcp = bsearch(argv[0], shell_cmds,
- X shcp - shell_cmds - 1,
- X sizeof(char *), shell_cmpr);
- X (*shellp)->s_shell = (shcp != NULL);
- X }
- X
- X /* run without COMMAND.COM if possible, 'cause it uses RAM */
- X if (!(*shellp)->s_shell)
- X runst = spawnvp(P_WAIT, argv[0], argv);
- X else
- X runst = system(scmd);
- X
- X shellunlink();
- X
- X if (runst == 0)
- X continue;
- X
- X /* uh-oh, an error */
- X if (runst == -1)
- X perror("make");
- X
- X errnum = talloc(18);
- X#ifdef MSDOS
- X errnum = itoa(runst, errnum, 10);
- X#else
- X sprintf(errnum, "%d", runst);
- X#endif
- X errmsg = (opts.keepon) ? "\007*** Ignoring Error code "
- X : "\007*** Error code ";
- X errmsg = tstrcat(errmsg, errnum);
- X terror(0, errmsg);
- X tfree(errmsg);
- X tfree(errnum);
- X
- X if (opts.keepon)
- X return (1);
- X
- X if (!opts.ignore && !(*shellp)->s_ignore)
- X exit(1);
- X }
- X
- X return (0);
- X}
- X
- X
- X/*
- X * shellinput - write the list of commands into a temp file, and return name
- X */
- Xchar *shellinput(shellp, eof)
- Xshellptr **shellp;
- Xchar *eof;
- X{
- X int eoflen;
- X char *scmd;
- X FILE *tfp;
- X
- X /* get rid of obvious errors */
- X if (shellp == NULL || *shellp == NULL)
- X return (NULL);
- X
- X eoflen = (eof) ? strlen(eof) : 0;
- X
- X /* find the name of a candidate temporary file */
- X tmpfn = tempnam(NULL, "mk");
- X
- X /* write contents to stdout when '-n' is specified */
- X if (opts.noexec && !opts.silent && !(**shellp)->s_silent)
- X tfp = stdout;
- X else
- X tfp = fopen(tmpfn, "w");
- X
- X while (*++*shellp)
- X {
- X /* break out the current shell command */
- X scmd = breakout((**shellp)->scmd);
- X
- X /* propogate the shell command attributes */
- X (**shellp)->s_silent = ((*shellp)[-1])->s_silent;
- X (**shellp)->s_ignore = ((*shellp)[-1])->s_ignore;
- X (**shellp)->s_shell = ((*shellp)[-1])->s_shell;
- X
- X /* see if we've reached the eof-word */
- X if (eof && !strncmp(scmd, eof, eoflen))
- X break;
- X
- X /* no there, so write out the command to the temp file */
- X if (tfp)
- X {
- X fputs(scmd, tfp);
- X fputc('\n', tfp);
- X }
- X
- X /* free the string allocated by breakout() */
- X tfree(scmd);
- X }
- X
- X if (tfp != stdout)
- X fclose(tfp);
- X
- X if (**shellp == NULL)
- X --* shellp; /* point at last shell command */
- X else
- X tfree(scmd); /* free EOF-word */
- X
- X return (tmpfn);
- X}
- X
- X
- X/*
- X * new_make - save current environment
- X * - call make() recursively (actually main())
- X * - clean up new environment
- X * - restore environment
- X */
- Xnew_make(argv)
- Xchar **argv;
- X{
- X targptr thead, tnext, tsuffix;
- X fileptr fhead, fnext;
- X symptr shead, snext;
- X shellptr shhead, shnext;
- X char **shcmds;
- X char **ttlist;
- X long tnow;
- X optnode topts;
- X int i;
- X
- X /* save all the globals */
- X tsuffix = suffix_targ;
- X thead = target_list;
- X fhead = file_list;
- X shead = symbol_list;
- X shhead = shell_list;
- X shcmds = shell_cmds;
- X ttlist = tlist;
- X tnow = now;
- X topts = opts;
- X
- X /* count the arguments */
- X for (i = 0; argv[i]; ++i)
- X tunquote(argv[i]);
- X
- X /* call ourselves recursively; this inherits flags */
- X ++make_level;
- X main(i, argv);
- X --make_level;
- X
- X /* we're back, so gotta clean up and dispose of a few things */
- X while (target_list)
- X {
- X tnext = target_list->tnext;
- X if (target_list->tpreq)
- X tfree(target_list->tpreq);
- X if (target_list->tshell)
- X tfree(target_list->tshell);
- X tfree(target_list);
- X target_list = tnext;
- X }
- X
- X while (file_list)
- X {
- X fnext = file_list->fnext;
- X tfree(file_list->fname);
- X tfree(file_list);
- X file_list = fnext;
- X }
- X
- X /* don't drop all symbols, just the new ones */
- X
- X while (symbol_list != shead)
- X {
- X snext = symbol_list->snext;
- X tfree(symbol_list->sname);
- X tfree(symbol_list->svalue);
- X tfree(symbol_list);
- X symbol_list = snext;
- X }
- X
- X while (shell_list)
- X {
- X shnext = shell_list->slink;
- X tfree(shell_list->scmd);
- X tfree(shell_list);
- X shell_list = shnext;
- X }
- X
- X /* restore our original globals */
- X suffix_targ = tsuffix;
- X target_list = thead;
- X file_list = fhead;
- X symbol_list = shead;
- X shell_list = shhead;
- X shell_cmds = shcmds;
- X tlist = ttlist;
- X now = tnow;
- X opts = topts;
- X}
- X
- X
- X#ifndef MSDOS
- Xint spawnvp(mode, path, args)
- Xint mode;
- Xchar *path;
- Xchar **args;
- X{
- X int pid = 0;
- X int retpid;
- X#ifdef BSD
- X union wait waitword;
- X#else
- X int waitword;
- X#endif
- X
- X if (mode != P_OVERLAY)
- X pid = fork();
- X
- X if (pid == 0)
- X execvp(path, args);
- X
- X while (((retpid = wait(&waitword)) != pid) && (retpid > 0))
- X ;
- X#ifdef BSD
- X return ((retpid == pid) ? waitword.w_retcode : (-1));
- X#else
- X return ((retpid == pid) ? ((waitword >> 8) & 0x00ff) : (-1));
- X#endif
- X}
- X#endif
- END_OF_FILE
- if test 7577 -ne `wc -c <'build.c'`; then
- echo shar: \"'build.c'\" unpacked with wrong size!
- fi
- # end of 'build.c'
- fi
- if test -f 'default.mk' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'default.mk'\"
- else
- echo shar: Extracting \"'default.mk'\" \(2487 characters\)
- sed "s/^X//" >'default.mk' <<'END_OF_FILE'
- X### this is the default makefile for Unix: default.mk
- X
- XSUFFIXES = .o .C .cxx .ec .c .y .l .s .sh
- X.SUFFIXES: $(SUFFIXES)
- X
- X# ASM section
- XAS = as
- XASFLAGS =
- XCOMPILE.s= $(AS) $(ASFLAGS)
- X.s:
- X $(AS) $(ASFLAGS) $<
- X.s.o:
- X $(AS) $(ASFLAGS) -o $@ $<
- X
- X# C section
- XCC = cc
- XCFLAGS = -O
- XCDEBUG = -g
- XCOMPILE.c= $(CC) $(CFLAGS) -c
- X.c:
- X $(LINK.c) -o $@ $< $(LDFLAGS)
- X
- X.c.o:
- X $(COMPILE.c) $<
- X
- X.c.i:
- X $(COMPILE.c) -P $<
- X
- X# CPP Section
- XCPP = CC
- XCPPFLAGS = -O
- XCPPDEBUG = -g
- XCOMPILE.cpp = $(CPP) $(CPPFLAGS)
- X.C .cxx:
- X $(CPP) $(CPPFLAGS) -o $@ $< $(LDFLAGS)
- X
- X.C.o .cxx.o:
- X $(COMPILE.cpp) $<
- X
- X.C.c .cxx.c:
- X $(COMPILE.cpp) -P $<
- X
- X# ESQL/C section
- XESQL = esql
- XEFLAGS =
- XCOMPILE.e= $(ESQL) $(EFLAGS)
- X.ec:
- X $(COMPILE.e) -e $<
- X $(LINK.c) -o $@ $*.c $(LDFLAGS)
- X
- X.ec.o:
- X $(COMPILE.e) -e $<
- X $(COMPILE.c) $*.c
- X
- X.ec.c:
- X $(COMPILE.e) -e $<
- X
- X# Lex section
- XLEX = lex
- XLFLAGS =
- XLEX.l = $(LEX) $(LFLAGS) -t
- X.l:
- X $(LEX.l) $< > $*.c
- X $(LINK.c) -o $@ $*.c $(LDFLAGS) -ll
- X
- X.l.o:
- X $(LEX.l) $< > $*.c
- X $(COMPILE.c) $*.c
- X
- X.l.c:
- X $(LEX.l) $< > $*.c
- X
- X# YACC section
- XYACC = yacc
- XYFLAGS =
- XYACC.y = $(YACC) $(YFLAGS)
- X.y:
- X $(YACC.y) $<
- X $(LINK.c) -o $@ y.tab.c $(LDFLAGS) -ly
- X $(RM) y.tab.c
- X
- X.y.o:
- X $(YACC.y) $<
- X $(COMPILE.c) -o $*.o y.tab.c
- X $(RM) y.tab.c
- X
- X.y.c:
- X $(YACC) $(YFLAGS) $<
- X $(MV) y.tab.c $@
- X
- X.y.h:
- X $(YACC) $(YFLAGS) -d $<
- X $(RM) y.tab.c
- X $(MV) y.tab.h $@
- X
- X# Shell script section
- X.sh:
- X cp $< $@
- X
- X# BSD Unix Misc section
- XA = .a
- XAR = ar
- XARFLAGS =
- XBIN = /usr/local/bin
- XCP = cp
- XE =
- XEDITOR = /usr/bin/vi
- XGFLAGS =
- XGET = get
- XLDEBUG =
- XLDFLAGS =
- XLD = ld
- XLIBDIR =
- XLINK.c = $(CC) $(CFLAGS)
- XMAKE = make
- XMKDEPEND = makedepend
- XMODEL =
- XMV = mv
- XO = .o
- XRANLIB = ranlib
- XRM = rm -f
- XSHELL = /bin/csh
- XSHELLCMD =
- XSTACK =
- X
- X# DOS Misc section
- X#A = .lib
- X#AR = lib
- X#ARFLAGS =
- X#BIN = C:\bin
- X#CP = cp
- X#E = .exe
- X#EDITOR = $(BIN)\vi
- X#GFLAGS =
- X#GET = echo cannot get
- X#LDEBUG = /link /noe /noi /co /st:$(STACK) $(LIBS)
- X#LDFLAGS = /link /noe /noi /st:$(STACK) $(LIBS)
- X#LD = $(CC) $(CFLAGS)
- X#LIBDIR = c:\msc5.1\lib
- X#LINK.c = $(CC) $(CFLAGS)
- X#MAKE = make
- X#MKDEPEND = mkdepend
- X#MODEL = S
- X#MV = mv
- X#O = .o
- X#RANLIB = echo cannot ranlib
- X#RM = rm -f
- X#SHELL = command /c
- X#SHELLCMD = break call cd chcp chdir cls copy ctty date del dir \
- X# echo erase exit for goto if md mkdir path pause prompt \
- X# rd rem ren rename rmdir set shift time type ver verify vol
- X#STACK = 2000
- END_OF_FILE
- if test 2487 -ne `wc -c <'default.mk'`; then
- echo shar: \"'default.mk'\" unpacked with wrong size!
- fi
- # end of 'default.mk'
- fi
- if test -f 'default.msc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'default.msc'\"
- else
- echo shar: Extracting \"'default.msc'\" \(3930 characters\)
- sed "s/^X//" >'default.msc' <<'END_OF_FILE'
- X### this is the default makefile for DOS: default.mk
- X
- XSUFFIXES = .cpp .c .asm .l .y .ec
- X.SUFFIXES: $(SUFFIXES)
- X
- X# ASM section
- XAS = masm
- XASFLAGS = /mx # don't convert to upper case
- XCOMPILE.s= $(AS) $(ASFLAGS)
- X.asm .asm.com:
- X $(COMPILE.s) $<;
- X $(LINK.c) -o $*.exe $*.obj $(LDFLAGS)
- X $(RM) $*.obj
- X exe2bin $*.exe $*.com
- X $(RM) $*.exe
- Xasm.exe:
- X $(COMPILE.s) $<;
- X $(LINK.c) -o $@ $*.obj $(LDFLAGS)
- X $(RM) $*.obj
- X.asm.obj:
- X $(COMPILE.s) $<;
- X.asm.o:
- X $(COMPILE.s) $<;
- X mv $*.obj $@
- X
- X# C section
- XCC = cl -A$(MODEL)
- XCFLAGS = /Ox /G2 # full optimization, 80286 opcodes
- XCDEBUG = /Od /Zi # no optimization, Codeview debuggable
- XCOMPILE.c= $(CC) $(CFLAGS) -c
- X.c.com:
- X $(COMPILE.cpp) -mt $< $(LIBS)
- X $(RM) $*.obj
- X.c .c.exe:
- X $(LINK.c) -o $@ $< $(LDFLAGS)
- X $(RM) $*.obj
- X.c.o:
- X $(COMPILE.c) /Fo$*.o $<
- X.c.obj:
- X $(COMPILE.c) $<
- X
- X# D section (ANSI C declaration headers)
- X.c.d:
- X echo "#ifndef NOPROTOTYPES" > $*.tmp
- X -$(COMPILE.c) -DNOPROTOTYPES -Zg $< >> $*.tmp
- X echo "#endif" >> $*.tmp
- X +updexhdr $*.tmp $*.d
- X $(RM) $*.tmp
- X
- X# I section (preprocessed C files)
- X.c.i:
- X $(COMPILE.c) -P $<
- X
- X# CPP Section
- XCPPINCDIR= c:\zortech\include
- XCPP = ztc -DNO_EXT_KEYS -I$(CPPINCDIR) -B -m$(MODEL)i # integer only
- XCPPF = ztc -DNO_EXT_KEYS -I$(CPPINCDIR) -B -m$(MODEL) # floats also
- XCPPFLAGS = -o # full optimization
- XCPPDEBUG = -g -co -s # codeview and stack checking
- XCOMPILE.cpp=$(CPP) $(CPPFLAGS)
- X.cpp .cpp.com:
- X $(COMPILE.cpp) -mt $<
- X $(RM) $*.obj
- X.cpp.exe:
- X $(COMPILE.cpp) $<
- X $(RM) $*.obj
- X.cpp.obj:
- X $(COMPILE.cpp) -c $<
- X.cpp.o:
- X $(COMPILE.cpp) -c $<
- X $(MV) $*.obj $@
- X.cpp.c:
- X $(COMPILE.cpp) -c -e -l$*.c $<
- X
- X# ESQL/C section
- XESQL = esql
- XEFLAGS =
- XCOMPILE.e= $(ESQL) $(EFLAGS)
- X.ec .ec.exe:
- X $(COMPILE.e) -e $<
- X $(LINK.c) -o $@ $*.c $(LDFLAGS) $(MODEL)libsql
- X $(RM) $*.obj $*.c
- X.ec.o:
- X $(COMPILE.e) -e $<
- X $(COMPILE.c) /Fo$*.o $*.c
- X $(RM) $*.c
- X.ec.obj:
- X $(COMPILE.e) -e $<
- X $(COMPILE.c) $*.c
- X $(RM) $*.c
- X.ec.c:
- X $(COMPILE.e) -e $<
- X
- X# Lex section
- XLEX = flex
- XLFLAGS = -I # interactive scanner
- XLEX.l = $(LEX) $(LFLAGS) -t
- X.l.com:
- X $(LEX.l) $< > $*.c
- X $(COMPILE.cpp) -mt $*.c
- X $(RM) $*.obj $*.c
- X.l .l.exe:
- X $(LEX.l) $< > $*.c
- X $(LINK.c) -o $@ $*.c $(LDFLAGS)
- X $(RM) $*.obj $*.c
- X.l.o:
- X $(LEX.l) $< > $*.c
- X $(COMPILE.c) /Fo$*.o $*.c
- X $(RM) $*.c
- X.l.obj:
- X $(LEX.l) $< > $*.c
- X $(COMPILE.c) $*.c
- X $(RM) $*.c
- X.l.c:
- X $(LEX.l) $< > $@
- X
- X# YACC Section
- XYACC = yacc
- XYFLAGS =
- XYACC.y = $(YACC) $(YFLAGS)
- X.y.com:
- X $(YACC.y) $<
- X $(COMPILE.cpp) -mt ytab.c
- X $(RM) $*.obj ytab.c
- X.y .y.exe:
- X $(YACC.y) $<
- X $(LINK.c) -o $@ ytab.c $(LDFLAGS)
- X $(RM) $*.obj ytab.c
- X.y.o:
- X $(YACC.y) $<
- X $(COMPILE.c) /Fo$*.o ytab.c
- X $(RM) ytab.c
- X.y.obj:
- X $(YACC.y) $<
- X $(COMPILE.c) ytab.c
- X $(RM) ytab.c
- X.y.h:
- X $(YACC.y) -d $<
- X $(RM) ytab.c
- X $(MV) ytab.h $@
- X.y.c:
- X $(YACC.y) $<
- X $(MV) ytab.c $@
- X
- X# BSD Unix Misc section
- X#A = .a
- X#AR = ar
- X#ARFLAGS =
- X#BIN = /usr/local/bin
- X#CP = cp
- X#E =
- X#EDITOR = /usr/bin/vi
- X#GFLAGS =
- X#GET = get
- X#LDEBUG =
- X#LDFLAGS =
- X#LD = ld
- X#LIBDIR =
- X#LINK.c = $(CC) $(CFLAGS)
- X#MAKE = make
- X#MKDEPEND = makedepend
- X#MODEL =
- X#MV = mv
- X#O = .o
- X#RANLIB = ranlib
- X#RM = rm -f
- X#SHELL = /bin/csh
- X#SHELLCMD =
- X#STACK =
- X
- X# DOS Misc section
- XA = .lib
- XAR = lib
- XARFLAGS =
- XBIN = C:\bin
- XCP = cp
- XE = .exe
- XEDITOR = $(BIN)\vi
- XGFLAGS =
- XGET = echo cannot get
- XLDEBUG = /link /noe /noi /co /st:$(STACK) $(LIBS)
- XLDFLAGS = /link /noe /noi /st:$(STACK) $(LIBS)
- XLD = $(CC) $(CFLAGS)
- XLIBDIR = c:\msc5.1\lib
- XLINK.c = $(CC) $(CFLAGS)
- XMAKE = make
- XMKDEPEND = mkdepend
- XMODEL = S
- XMV = mv
- XO = .o
- XRANLIB = echo cannot ranlib
- XRM = rm -f
- XSHELL = command /c
- XSHELLCMD = break call cd chcp chdir cls copy ctty date del dir \
- X echo erase exit for goto if md mkdir path pause prompt \
- X rd rem ren rename rmdir set shift time type ver verify vol
- XSTACK = 2000
- END_OF_FILE
- if test 3930 -ne `wc -c <'default.msc'`; then
- echo shar: \"'default.msc'\" unpacked with wrong size!
- fi
- # end of 'default.msc'
- fi
- if test -f 'make.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'make.h'\"
- else
- echo shar: Extracting \"'make.h'\" \(3424 characters\)
- sed "s/^X//" >'make.h' <<'END_OF_FILE'
- X/*
- X * make.h
- X *
- X * 88-10-01 v1.0 created by greg yachuk, placed in the public domain
- X * 88-10-06 v1.1 changed prerequisite list handling
- X * 88-11-11 v1.2 fixed some bugs and added environment variables
- X * 89-07-12 v1.3 stop appending shell commands, and flush output
- X * 89-08-01 v1.4 AB lots of new options and code
- X * 89-10-30 v1.5 -f -S -q options, took some changes from v1.4
- X * 90-04-18 v1.6 -b -- -W options, emulate <<, non-BSD cleanup
- X */
- X
- X#define MAKEINI "default.mk"
- X
- X#ifdef MSDOS
- X#define PATH_SEPARATOR ";"
- X#define FILE_SEPARATOR ":/\\"
- X#define SHELL_METAS "<|>"
- X#else
- X#define PATH_SEPARATOR ":"
- X#define FILE_SEPARATOR "/"
- X#define SHELL_METAS "<|>`*?()[];&$"
- X#endif
- X
- X#define MAXNEGTIME 0x80000000
- X
- X#define equal(s,t) (!strcmp((s),(t)))
- X#define get_target(t) hash_target((t), NULL)
- X#define get_file(f) hash_file((f), NULL)
- X#define append_preq(t,p) (fileptr*)append_node((char**)(t),(char**)(p),sizeof(fileptr*))
- X#define append_shell(t,s) (shellptr*)append_node((char**)(t),(char**)(s),sizeof(shellptr*))
- X
- Xtypedef unsigned short t_mask;
- X
- Xtypedef struct targnode
- X{
- X t_mask tmask; /* mask to avoid string compares */
- X struct targnode *tnext; /* next target in global target list */
- X struct filenode *tfile; /* file node for this target */
- X struct filenode **tpreq;/* pre-req list for this target */
- X struct shellnode **tshell; /* command list for this target */
- X} targnode, *targptr;
- X
- Xtypedef struct filenode
- X{
- X t_mask fmask; /* mask to avoid string compares */
- X char *fname; /* name of this file (targ, preq...) */
- X long ftime; /* last MODIFY time for this file */
- X struct filenode *fnext; /* next file node in global file list */
- X} filenode, *fileptr;
- X
- Xtypedef struct shellnode
- X{
- X char *scmd; /* text of command */
- X unsigned s_silent:1; /* don't echo before executing */
- X unsigned s_ignore:1; /* ignore exit status */
- X unsigned s_shell:1; /* force spawning of command.com */
- X struct shellnode *slink;/* next shell node in global list */
- X} shellnode, *shellptr;
- X
- Xtypedef struct symnode
- X{
- X t_mask smask; /* mask to avoid string compares */
- X char *sname; /* name of a symbol */
- X char *svalue; /* value of a symbol */
- X struct symnode *snext; /* next symbol node in global list */
- X int scmd; /* command line macro? */
- X int slevel; /* level of new_make() */
- X} symnode, *symptr;
- X
- Xtypedef struct optnode
- X{
- X unsigned depend; /* -d */
- X unsigned display:1; /* -D */
- X unsigned envirn:1; /* -e */
- X unsigned ignore:1; /* -i */
- X unsigned keepon:1; /* -k */
- X unsigned noexec:1; /* -n */
- X unsigned query:1; /* -q */
- X unsigned silent:1; /* -s */
- X unsigned touch:1; /* -t */
- X char *make; /* current value of $(MAKE) */
- X} optnode;
- X
- Xextern targptr target_list; /* global list of targets */
- Xextern fileptr file_list; /* global list of file nodes */
- Xextern symptr symbol_list; /* global list of symbol nodes */
- Xextern shellptr shell_list; /* global list of shell nodes */
- X
- Xextern char **shell_cmds; /* commands which force usage of SHELL */
- X
- Xextern int make_level; /* level of new_make() */
- X
- Xextern targptr first_targ; /* first target (if nothing named) */
- Xextern targptr suffix_targ; /* target node of ".SUFFIXES" */
- X
- Xextern optnode opts; /* various options */
- Xextern char **tlist; /* list of command line targets */
- Xextern long now; /* current time */
- X
- X#ifndef MSDOS
- Xchar *getenv();
- X
- X#define P_WAIT 1
- X#define P_NOWAIT 2
- X#define P_OVERLAY 3
- X#endif /* MSDOS */
- END_OF_FILE
- if test 3424 -ne `wc -c <'make.h'`; then
- echo shar: \"'make.h'\" unpacked with wrong size!
- fi
- # end of 'make.h'
- fi
- if test -f 'makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'makefile'\"
- else
- echo shar: Extracting \"'makefile'\" \(1286 characters\)
- sed "s/^X//" >'makefile' <<'END_OF_FILE'
- X# name of this program
- XNAME = make
- X
- X# define the FLAGS as required for MSDOS or Unix
- XCFLAGS = -O
- XLDFLAGS =
- X
- XSRCS = make.c parse.c build.c tstring.c
- XOBJS = make.o parse.o build.o tstring.o
- XPROG = $(NAME)$E
- X
- X# define your installation directory
- XBIN = $(HOME)/bin
- X
- X# archive utility
- XARCADD = zoo a
- X
- X# files to archive
- XARCS = decl.h make.h tstring.h make.c parse.c build.c tstring.c \
- X default.mk default.bsd makefile makefile.bsd make.doc \
- X README $(PROG)
- X
- Xall: $(PROG)
- X
- X$(PROG): $(OBJS)
- X $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LDFLAGS)
- X
- Xarc: $(NAME).zoo
- Xzoo: $(NAME).zoo
- X
- X$(NAME).zoo: $(ARCS)
- X $(RM) $(NAME).zoo
- X $(ARCADD) $(NAME).zoo $(ARCS)
- X
- Xinstall: $(BIN)/$(PROG) $(BIN)/default.mk
- X$(BIN)/$(PROG): $(PROG)
- X cp $(PROG) $(BIN)/$(PROG)
- X$(BIN)/default.mk: default.mk
- X cp default.mk $(BIN)/default.mk
- X
- Xclean:
- X -$(RM) *.o
- X -$(RM) *.bak
- X
- X# use this to check the size of the program (use chkdsk if necessary)
- Xsize:
- X pmap
- X
- Xdepend:
- X $(MKDEPEND) $(SRCS) > makefile.new
- X $(MV) makefile makefile.BAK
- X $(MV) makefile.new makefile
- X
- Xtest: $(OBJS)
- X link @<<END_OF_LINK
- X $(OBJS)
- X x$(NAME)
- X /cparmaxalloc:1 /noe /stack:2000
- X $(LIBS)
- X END_OF_LINK
- X
- X# DO NOT DELETE THIS LINE
- X
- Xmake.o: make.h tstring.h decl.h
- Xparse.o: make.h tstring.h decl.h
- Xbuild.o: make.h tstring.h decl.h
- Xtstring.o: tstring.h
- END_OF_FILE
- if test 1286 -ne `wc -c <'makefile'`; then
- echo shar: \"'makefile'\" unpacked with wrong size!
- fi
- # end of 'makefile'
- fi
- if test -f 'makefile.msc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'makefile.msc'\"
- else
- echo shar: Extracting \"'makefile.msc'\" \(1483 characters\)
- sed "s/^X//" >'makefile.msc' <<'END_OF_FILE'
- X# name of this program
- XNAME = make
- X
- X# define the FLAGS as required for MSDOS or Unix
- XCFLAGS = /Oals /Gs /G2
- XLDFLAGS = /link /cparmaxalloc:1 /noe /stack:2000 $(LIBS)
- X
- XSRCS = make.c parse.c build.c tstring.c
- XOBJS = make.o parse.o build.o tstring.o
- XPROG = $(NAME)$E
- X
- X# define your installation directory
- XBIN = c:/bin
- X
- X# archive utility
- XARCADD = zoo a
- X
- X# files to archive
- XARC1 = decl.h make.h tstring.h make.c parse.c build.c tstring.c default.mk
- XARC2 = default.bsd makefile makefile.bsd make.doc README $(PROG)
- XARCS = $(ARC1) $(ARC2)
- X
- Xall: $(PROG)
- X
- X$(PROG): $(OBJS)
- X echo out of date dependents($@): $?
- X $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LDFLAGS)
- X
- Xarc: $(NAME).zoo
- Xzoo: $(NAME).zoo
- X
- X$(NAME).zoo: $(ARCS)
- X $(RM) $(NAME).zoo
- X $(ARCADD) $(NAME).zoo $(ARC1)
- X $(ARCADD) $(NAME).zoo $(ARC2)
- X
- Xinstall: $(BIN)/$(PROG) $(BIN)/default.mk
- X$(BIN)/$(PROG): $(PROG)
- X cp $(PROG) $(BIN)/$(PROG)
- X$(BIN)/default.mk: default.mk
- X cp default.mk $(BIN)/default.mk
- X
- Xclean:
- X -$(RM) *.o
- X -$(RM) *.bak
- X
- X# use this to check the size of the program (use chkdsk if necessary)
- Xsize:
- X pmap
- X
- Xdepend:
- X $(MKDEPEND) $(SRCS) > makefile.new
- X $(MV) makefile makefile.BAK
- X $(MV) makefile.new makefile
- X
- Xtest: $(OBJS)
- X echo out of date dependents($@): $?
- X link @<<END_OF_LINK
- X $(OBJS)
- X x$(NAME)
- X /cparmaxalloc:1 /noe /stack:2000
- X $(LIBS)
- X END_OF_LINK
- X echo End Of Link
- X
- X# DO NOT DELETE THIS LINE
- X
- Xmake.o: make.h tstring.h decl.h
- Xparse.o: make.h tstring.h decl.h
- Xbuild.o: make.h tstring.h decl.h
- Xtstring.o: tstring.h
- END_OF_FILE
- if test 1483 -ne `wc -c <'makefile.msc'`; then
- echo shar: \"'makefile.msc'\" unpacked with wrong size!
- fi
- # end of 'makefile.msc'
- fi
- if test -f 'parse.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'parse.c'\"
- else
- echo shar: Extracting \"'parse.c'\" \(17139 characters\)
- sed "s/^X//" >'parse.c' <<'END_OF_FILE'
- X/*
- X * parse.c
- X *
- X * 88-10-01 v1.0 created by greg yachuk, placed in the public domain
- X * 88-10-06 v1.1 changed prerequisite list handling
- X * 88-11-11 v1.2 fixed some bugs and added environment variables
- X * 89-07-12 v1.3 stop appending shell commands, and flush output
- X * 89-08-01 v1.4 AB lots of new options and code
- X * 89-10-30 v1.5 -f -S -q options, took some changes from v1.4
- X * 90-04-18 v1.6 -b -- -W options, emulate <<, non-BSD cleanup
- X */
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <string.h>
- X#ifdef MSDOS
- X#include <stdlib.h>
- X#endif
- X
- X#include "make.h"
- X#include "tstring.h"
- X#include "decl.h"
- X
- X/*
- X * parse - read (text) makefile, and parse
- X * - close file before returing
- X *
- X * lines have the following format:
- X * # with or without preceeding spaces/tabs (comment line)
- X * <TAB> commands (shell line)
- X * name = stuff (macro)
- X * name += stuff (macro)
- X * targ [targ...] : [pre-req...] [; shell cmd ] (target line)
- X */
- Xparse(fd)
- XFILE *fd;
- X{
- X char *input;
- X char *ip;
- X char *colonp;
- X char schar;
- X int ntargs, npreqs, nshell;
- X int tmax, pmax, smax;
- X targptr *targs;
- X fileptr *preqs;
- X shellptr *shells;
- X
- X if (fd == NULL)
- X return (0);
- X
- X /* start off with a short list of targets */
- X targs = (targptr *) grow_list(NULL, &tmax);
- X preqs = (fileptr *) grow_list(NULL, &pmax);
- X shells = (shellptr *) grow_list(NULL, &smax);
- X
- X ntargs = npreqs = nshell = 0;
- X
- X /* maximize buffering */
- X setvbuf(fd, NULL, _IOFBF, 2048);
- X
- X while ((input = tgets(fd)) != NULL)
- X {
- X /* punt on comments and blank lines */
- X for (ip = input; isspace(*ip); ++ip);
- X if (*ip == '#' || *ip == '\0')
- X continue;
- X
- X /* process include files */
- X if (!strncmp(ip, "include", 7))
- X {
- X /* skip spaces AFTER "include" */
- X for (ip += 7; isspace(*ip); ++ip);
- X
- X /* process macros in the filename */
- X ip = breakout(ip);
- X
- X /* parse the makefile */
- X if (!parse(fopen(ip, "r")))
- X terror(1, tstrcat("cannot open ", ip));
- X
- X /* free up the broken-out string */
- X tfree(ip);
- X continue; /* get next input line */
- X }
- X
- X /* display the makefile line ? */
- X if (opts.display)
- X puts(input);
- X
- X /* get rid of comments and preceeding spaces */
- X for (colonp = ip; *colonp && *colonp != '#'; ++colonp)
- X {
- X if (*colonp == '\'' || *colonp == '"')
- X colonp = tstrspan(colonp);
- X }
- X
- X for (--colonp; colonp >= ip && isspace(*colonp); --colonp);
- X
- X /* we *know* that some non-space is on this line, from above */
- X if (colonp >= ip)
- X *++colonp = '\0';
- X
- X /* see if we have a shell command */
- X if (isspace(*input))
- X {
- X if (ntargs == 0)
- X terror(1, "rules must be after target");
- X got_shell:
- X if (nshell == smax)
- X {
- X shells = (shellptr *)
- X grow_list((char **) shells, &smax);
- X }
- X shells[nshell++] = add_shell(ip);
- X continue;
- X }
- X
- X /* not a shell line, so must be a target or a macro */
- X if (ntargs != 0)
- X {
- X /* link previous preq's and shell's */
- X targs[ntargs] = NULL;
- X preqs[npreqs] = NULL;
- X shells[nshell] = NULL;
- X link_targs(targs, preqs, shells);
- X ntargs = npreqs = nshell = 0;
- X }
- X
- X /* don't break out symbols until macro is invoked */
- X if (add_macro(ip, 0))
- X continue;
- X
- X /* okay, we have a target line; break out macro symbols */
- X input = breakout(ip);
- X
- X /* just look for tokens with standard isspace() separators */
- X ip = token(input, NULL, &schar);
- X while (ip)
- X {
- X colonp = strchr(ip, ':');
- X#ifdef MSDOS
- X /* need to allow c:/bin/make.exe as a target */
- X if (colonp && colonp - ip == 1)
- X colonp = strchr(colonp + 1, ':');
- X#endif
- X if (colonp)
- X {
- X /* got a separator */
- X *colonp = '\0';
- X
- X /* if at front of token, target is done */
- X if (colonp == ip)
- X break;
- X }
- X
- X if (ntargs == tmax)
- X targs = (targptr *) grow_list((char **) targs,
- X &tmax);
- X targs[ntargs] = add_target(ip);
- X
- X /* make sure we don't save .INIT as our 1st target */
- X if (first_targ == NULL && *ip != '.')
- X first_targ = targs[ntargs];
- X ++ntargs;
- X
- X if (colonp)
- X break;
- X ip = token(NULL, NULL, &schar);
- X }
- X
- X /* a target line without a colon? naughty, naughty! */
- X if (!colonp)
- X terror(-1, "Unexpected end of line seen");
- X
- X/*
- X * taking care of four possible cases:
- X * 1) object : source
- X * 2) object: source
- X * 3) object :source
- X * 4) object:source
- X */
- X
- X if (colonp && *++colonp)
- X ip = colonp;
- X else
- X ip = token(NULL, NULL, &schar);
- X
- X /* link the pre-req's */
- X while (ip)
- X {
- X if ((colonp = strchr(ip, ';')) != NULL)
- X {
- X ip[strlen(ip)] = schar;
- X *colonp = '\0';
- X }
- X
- X if (*ip)
- X {
- X if (npreqs == pmax)
- X {
- X preqs = (fileptr *)
- X grow_list((char **) preqs,
- X &pmax);
- X }
- X
- X preqs[npreqs++] = add_file(ip);
- X }
- X
- X if (colonp)
- X {
- X ip = colonp + 1;
- X goto got_shell;
- X }
- X
- X ip = token(NULL, NULL, &schar);
- X }
- X
- X /* gotta free the line allocated by breakout() */
- X tfree(input);
- X }
- X
- X /* link up any dangling dependants */
- X if (ntargs != 0)
- X {
- X targs[ntargs] = NULL;
- X preqs[npreqs] = NULL;
- X shells[nshell] = NULL;
- X link_targs(targs, preqs, shells);
- X }
- X
- X /* clean up our mallocs */
- X tfree(targs);
- X tfree(preqs);
- X tfree(shells);
- X
- X fclose(fd);
- X return (1);
- X}
- X
- X
- X/*
- X * link_targs - force a list of targs to point to same preq's and shell's
- X */
- Xlink_targs(targs, preqs, shells)
- Xtargptr *targs;
- Xfileptr *preqs;
- Xshellptr *shells;
- X{
- X while (targs && *targs)
- X {
- X /* process some special targets */
- X if ((*targs)->tfile->fname[0] == '.')
- X {
- X if (equal((*targs)->tfile->fname, ".SILENT"))
- X opts.silent = 1;
- X else
- X if (equal((*targs)->tfile->fname, ".IGNORE"))
- X opts.ignore = 1;
- X else
- X if (equal((*targs)->tfile->fname, ".SUFFIXES"))
- X /*
- X * set `suffix_targ' to speed up
- X * `default_rule'
- X */
- X suffix_targ = *targs;
- X
- X /* special rule has preq's reset */
- X /* normally, preq's are merely appended */
- X if (*preqs == NULL && (*targs)->tpreq != NULL)
- X {
- X tfree((*targs)->tpreq);
- X (*targs)->tpreq = NULL;
- X }
- X
- X /* special rules have their shell commands replaced */
- X if ((*targs)->tshell != NULL && *shells != NULL)
- X {
- X shellptr *sp;
- X
- X for (sp = (*targs)->tshell; *sp; ++sp)
- X tfree(*sp);
- X tfree((*targs)->tshell);
- X (*targs)->tshell = NULL;
- X }
- X }
- X
- X /* each target in the list points to the preq's and shell's */
- X (*targs)->tpreq = append_preq((*targs)->tpreq, preqs);
- X
- X /* we cannot expand the list of shell commands */
- X if ((*targs)->tshell != NULL && *shells != NULL)
- X {
- X terror(1, tstrcat("Too many rules defined for target ",
- X (*targs)->tfile->fname));
- X }
- X (*targs)->tshell = append_shell((*targs)->tshell, shells);
- X ++targs;
- X }
- X}
- X
- X
- X/* macros must have the format: WORD = more stuff
- X * WORD= more stuff
- X * WORD =more stuff
- X * WORD=more stuff
- X * or: WORD += more stuff
- X * WORD +=more stuff
- X *
- X * it is assumed that there is no leading whitespace in `input'
- X */
- Xadd_macro(input, scmd)
- Xchar *input;
- Xint scmd;
- X{
- X char *eqsign;
- X char *value;
- X symptr symp;
- X
- X /* gotta have an '=' to be a macro */
- X eqsign = strchr(input, '=');
- X if (eqsign == NULL)
- X return (0);
- X
- X /* make sure we catch imbedded '='s (e.g. MACRO=STUFF) */
- X for (value = input; *value && !isspace(*value); ++value);
- X if (value > eqsign)
- X value = eqsign;
- X
- X /* terminate the macro name */
- X *value = '\0';
- X
- X /* find start of value */
- X for (value = eqsign + 1; isspace(*value); ++value);
- X
- X /* look for concat character */
- X --eqsign;
- X
- X if (eqsign < input || (eqsign == input && *eqsign == '+'))
- X terror(1, "Badly formed macro");
- X
- X if (*eqsign == '+')
- X {
- X /* append to the current macro definition */
- X *eqsign = '\0';
- X symp = get_symbol(input, scmd);
- X if (symp->scmd && !scmd)
- X return (1);
- X if (symp->slevel < make_level)
- X symp = dup_symbol(symp, symp->svalue);
- X if (symp->svalue)
- X {
- X eqsign = tstrcat(symp->svalue, " ");
- X value = tstrcat(eqsign, value);
- X tfree(eqsign);
- X tfree(symp->svalue);
- X symp->svalue = value;
- X return (1);
- X }
- X }
- X
- X add_symbol(input, value, scmd);
- X return (1);
- X}
- X
- X
- X/*
- X * add_symbol - add a <name,value> pair to the symbol table
- X * - override existing symbol value
- X * - mark as either command-line macro or not
- X */
- Xadd_symbol(name, value, scmd)
- Xchar *name;
- Xchar *value;
- Xint scmd;
- X{
- X symptr symp;
- X
- X symp = get_symbol(name, scmd);
- X if (symp->scmd & !scmd)
- X return;
- X if (symp->slevel < make_level)
- X symp = dup_symbol(symp, NULL); /* don't dup the value */
- X if (symp->svalue)
- X tfree(symp->svalue);
- X symp->svalue = tstrcpy(value);
- X symp->scmd = scmd;
- X}
- X
- X
- X/*
- X * get_symbol - find a symbol in the symbol table
- X * - if non-extant, create <name,NULL>
- X * - return created or found symbol node
- X */
- Xsymptr get_symbol(name, scmd)
- Xchar *name;
- Xint scmd;
- X{
- X symptr symp;
- X t_mask mask;
- X char *np;
- X
- X /* use `mask' to screen out most string comparisons */
- X mask = 0;
- X np = name;
- X while (*np)
- X mask += *np++;
- X
- X /* linear search through symbol list */
- X for (symp = symbol_list; symp != NULL; symp = symp->snext)
- X {
- X if (mask != symp->smask)
- X continue;
- X
- X if (equal(name, symp->sname))
- X return (symp);
- X }
- X
- X symp = tnew(symnode); /* allocate symbol node */
- X symp->smask = mask; /* record mask for later */
- X symp->sname = tstrcpy(name); /* allocate string and copy name */
- X symp->scmd = scmd; /* command line macro? */
- X symp->slevel = make_level; /* current new_make() level */
- X
- X /* get the value from the environment, if it is there */
- X
- X if ((symp->svalue = getenv(name)) != NULL)
- X {
- X symp->svalue = tstrcpy(symp->svalue);
- X
- X /*
- X * if `-e', let command line macros override, but not macro
- X * assignments in the makefile.
- X */
- X if (opts.envirn)
- X symp->scmd = 1;
- X }
- X
- X symp->snext = symbol_list; /* link to head of symbol list */
- X symbol_list = symp;
- X
- X return (symp);
- X}
- X
- X
- X/*
- X * dup_sym - duplicate a symbol node, but at current new_make() level
- X */
- Xsymptr dup_symbol(symp, value)
- Xsymptr symp;
- Xchar *value;
- X{
- X symptr nsp;
- X
- X nsp = tnew(symnode); /* allocate symbol node */
- X nsp->smask = symp->smask; /* record mask for later */
- X nsp->sname = tstrcpy(symp->sname); /* allocate string and copy
- X * name */
- X nsp->svalue = (value == NULL) ? NULL : tstrcpy(value);
- X nsp->scmd = symp->scmd; /* command line macro? */
- X nsp->slevel = make_level; /* current new_make() level */
- X
- X nsp->snext = symbol_list; /* link to head of symbol list */
- X symbol_list = nsp;
- X
- X return (nsp);
- X}
- X
- X
- X/*
- X * add_target - return extant target node, or create new one
- X */
- Xtargptr add_target(name)
- Xchar *name;
- X{
- X t_mask mask;
- X targptr targp;
- X fileptr filep;
- X
- X /* each target must have a file node */
- X filep = add_file(name);
- X
- X /* see if target already exists */
- X targp = hash_target(name, &mask);
- X if (targp)
- X return (targp);
- X
- X /* oh well, gotta create one */
- X targp = tnew(targnode); /* allocate a target node */
- X targp->tmask = mask; /* save mask for later */
- X targp->tfile = filep; /* save pointer to file node */
- X targp->tpreq = NULL; /* no pre-req's yet */
- X targp->tshell = NULL; /* no shell lines yet */
- X
- X targp->tnext = target_list; /* link to front of target list */
- X target_list = targp;
- X
- X return (targp);
- X}
- X
- X
- X/*
- X * hash_target - look up target (by name) in target list
- X * - return target node or NULL
- X * - if requested, also return the mask
- X */
- Xtargptr hash_target(name, maskp)
- Xchar *name;
- Xt_mask *maskp;
- X{
- X targptr targp;
- X t_mask mask;
- X char *np;
- X
- X /* use `mask' to screen out most string comparisons */
- X mask = 0;
- X np = name;
- X while (*np)
- X mask += *np++;
- X
- X /* see if we gotta return it */
- X if (maskp != NULL)
- X *maskp = mask;
- X
- X /* linear search through target list */
- X for (targp = target_list; targp != NULL; targp = targp->tnext)
- X {
- X if (mask != targp->tmask)
- X continue;
- X
- X /* target name is ONLY stored in the file node */
- X if (equal(name, targp->tfile->fname))
- X return (targp);
- X }
- X
- X /* nope, no target here */
- X return (NULL);
- X}
- X
- X
- X/*
- X * add_file - return a found or created file node
- X */
- Xfileptr add_file(name)
- Xchar *name;
- X{
- X t_mask mask;
- X fileptr filep;
- X
- X /* see if file node already exists */
- X filep = hash_file(name, &mask);
- X if (filep)
- X return (filep);
- X
- X filep = tnew(filenode); /* allocate new file node */
- X filep->fmask = mask; /* save mask for later */
- X filep->fname = tstrcpy(name); /* allocate string and copy name */
- X filep->ftime = MAXNEGTIME; /* init MODIFY time to long time ago */
- X
- X filep->fnext = file_list; /* link to head of file list */
- X file_list = filep;
- X
- X return (filep);
- X}
- X
- X
- X/*
- X * hash_file - look up file (by name) in file list
- X * - return file node or NULL
- X * - if requested, also return the mask
- X */
- Xfileptr hash_file(name, maskp)
- Xchar *name;
- Xt_mask *maskp;
- X{
- X fileptr filep;
- X t_mask mask;
- X char *np;
- X
- X /* use `mask' to screen out most string comparisons */
- X mask = 0;
- X np = name;
- X while (*np)
- X mask += *np++;
- X
- X /* see if we gotta return it */
- X if (maskp != NULL)
- X *maskp = mask;
- X
- X /* linear search through file list */
- X for (filep = file_list; filep != NULL; filep = filep->fnext)
- X {
- X if (filep->fmask != mask)
- X continue;
- X
- X if (equal(filep->fname, name))
- X return (filep);
- X }
- X
- X /* nope, no file here */
- X return (NULL);
- X}
- X
- X
- X/*
- X * append_node - add a node to the end of an array of nodes
- X */
- Xchar **append_node(node, adds, size)
- Xchar **node;
- Xchar **adds;
- Xint size;
- X{
- X int addlen, len;
- X
- X for (addlen = 0; adds[addlen] != NULL; ++addlen);
- X if (addlen++ == 0)
- X return (node);
- X
- X len = 0;
- X
- X if (node != NULL)
- X {
- X for (; node[len] != NULL; ++len);
- X node = (char **) trealloc((char *) node, (len + addlen) * size);
- X }
- X else
- X node = (char **) talloc(addlen * size);
- X
- X memcpy(node + len, adds, addlen * size);
- X return (node);
- X}
- X
- X/*
- X * add_shell - create a new shell node, and add to end of given list
- X */
- Xshellptr add_shell(input)
- Xchar *input;
- X{
- X shellptr snode;
- X
- X snode = tnew(shellnode);/* allocate a new shell node */
- X snode->s_shell = snode->s_ignore = snode->s_silent = 0;
- X
- X for (; isspace(*input); ++input); /* skip over leading spaces */
- X for (;; ++input)
- X {
- X if (*input == '+')
- X snode->s_shell = 1; /* must use command.com */
- X else
- X if (*input == '-')
- X snode->s_ignore = 1; /* ignore return value */
- X else
- X if (*input == '@')
- X snode->s_silent = 1; /* don't echo command */
- X else
- X break;
- X }
- X
- X snode->scmd = tstrcpy(input); /* allocate string and copy command */
- X
- X snode->slink = shell_list; /* attach to global list */
- X shell_list = snode;
- X
- X return (snode);
- X}
- X
- X
- X/*
- X * breakout - replace macro names with values
- X * - apply recursively
- X * note: allocates (and returns) a string which must be freed
- X */
- Xchar *breakout(input)
- Xchar *input;
- X{
- X char *dest, *dend;
- X char *dp;
- X int dlen;
- X int tlen;
- X int state;
- X char symname[100];
- X char *sp;
- X symptr symp;
- X int slen;
- X char endch;
- X
- X /* allocate a string twice as long as input string */
- X
- X dlen = strlen(input) * 2;
- X dest = dp = talloc(dlen);
- X dend = dest + dlen;
- X
- X/*
- X * state machine with 4 states
- X * 0) normal text -- just copy
- X * 1) starting macro -- define end char (e.g. ')', '}')
- X * 2) macro name -- copy to a buffer
- X * 3) end of macro -- look up value, and copy
- X */
- X state = 0;
- X
- X while (*input || state == 3)
- X {
- X /* if we don't have enough room, double size of string */
- X if (dp == dend)
- X {
- X dlen *= 2;
- X tlen = dp - dest;
- X dest = trealloc(dest, dlen);
- X dp = dest + tlen;
- X dend = dest + dlen;
- X }
- X
- X switch (state)
- X {
- X case 0:
- X if (*input == '$')
- X state = 1; /* found a macro */
- X else
- X *dp++ = *input++;
- X break;
- X
- X case 1:
- X state = 2; /* only in this state for 1 char */
- X sp = symname;
- X switch (*++input)
- X {
- X case '$':
- X *dp++ = '$';
- X state = 0;
- X break;
- X case '(':
- X endch = ')';
- X break;
- X case '{':
- X endch = '}';
- X break;
- X default:
- X /* single char; go to state 3 immediately */
- X *sp++ = *input;
- X state = 3;
- X break;
- X }
- X ++input;/* skip bracket (or character) */
- X break;
- X
- X case 2:
- X if (*input == endch)
- X state = 3;
- X else
- X *sp++ = *input;
- X
- X if ((sp - symname) >= (sizeof symname / sizeof symname[0]))
- X {
- X sp[-1] = '\0';
- X terror(1,
- X tstrcat("Macro too long (limit 100 chars): ",
- X symname));
- X }
- X
- X ++input;/* make sure we skip end char */
- X break;
- X
- X case 3:
- X *sp = '\0';
- X symp = get_symbol(symname, 0);
- X sp = symp->svalue;
- X slen = -1;
- X while (sp && *sp)
- X {
- X /*
- X * if value has a macro in it, we must
- X * process recursively
- X */
- X if (*sp == '$')
- X {
- X sp = breakout(symp->svalue);
- X /* now guaranteed not to have a '$' */
- X slen = strlen(sp);
- X break;
- X }
- X ++sp;
- X }
- X
- X if (slen == -1)
- X {
- X /* value did NOT have a macro */
- X slen = (sp - symp->svalue);
- X sp = symp->svalue;
- X }
- X
- X /* if we have not enough room, expand */
- X if (slen >= (dend - dp))
- X {
- X /* use slen to make sure that we can fit */
- X dlen = dlen * 2 + slen;
- X tlen = dp - dest;
- X dest = trealloc(dest, dlen);
- X dp = dest + tlen;
- X dend = dest + dlen;
- X }
- X
- X /* if length is zero, don't bother to copy */
- X if (slen)
- X {
- X strcpy(dp, sp);
- X dp += slen;
- X }
- X
- X if (sp != symp->svalue)
- X tfree(sp); /* must've called `breakout' */
- X
- X state = 0; /* and we are back to text */
- X break;
- X }
- X }
- X
- X if (state != 0)
- X terror(1, tstrcat("Improper macro.\n", dest));
- X
- X *dp = '\0'; /* terminate the string */
- X return (dest); /* and return it */
- X}
- END_OF_FILE
- if test 17139 -ne `wc -c <'parse.c'`; then
- echo shar: \"'parse.c'\" unpacked with wrong size!
- fi
- # end of 'parse.c'
- fi
- if test -f 'tstring.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tstring.c'\"
- else
- echo shar: Extracting \"'tstring.c'\" \(5480 characters\)
- sed "s/^X//" >'tstring.c' <<'END_OF_FILE'
- X/*
- X * tstring.c
- X *
- X * 88-10-01 v1.0 created by greg yachuk, placed in the public domain
- X * 88-10-06 v1.1 changed prerequisite list handling
- X * 88-11-11 v1.2 fixed some bugs and added environment variables
- X * 89-07-12 v1.3 stop appending shell commands, and flush output
- X * 89-08-01 v1.4 AB lots of new options and code
- X * 89-10-30 v1.5 -f -S -q options, took some changes from v1.4
- X * 90-04-18 v1.6 -b -- -W options, emulate <<, non-BSD cleanup
- X */
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <malloc.h>
- X#include <string.h>
- X
- X#include "tstring.h"
- X
- X
- Xchar *talloc(n)
- Xint n;
- X{
- X char *s;
- X
- X s = malloc(n);
- X if (s == NULL)
- X terror(1, "no free memory");
- X return (s);
- X}
- X
- X
- Xchar *trealloc(s, n)
- Xchar *s;
- Xint n;
- X{
- X s = realloc(s, n);
- X if (s == NULL)
- X talloc(n); /* force an error */
- X return (s);
- X}
- X
- X
- Xchar *tstrncpy(s, n)
- Xchar *s;
- Xint n;
- X{
- X s = strncpy(talloc(n + 1), s, n);
- X s[n] = '\0';
- X return (s);
- X}
- X
- X
- Xterror(n, s)
- Xint n;
- Xchar *s;
- X{
- X fputs("Make: ", stderr);
- X fputs(s, stderr);
- X putc('\n', stderr);
- X if (n)
- X exit(n);
- X}
- X
- X
- X/*
- X * tstrspan - move to the end of a quoted string, ignoring escaped quotes
- X */
- Xchar *tstrspan(str)
- Xchar *str;
- X{
- X char quote;
- X
- X if (*str != '\'' && *str != '"')
- X return (str + 1);
- X
- X quote = *str++;
- X
- X while (*str && *str != quote)
- X {
- X /* check for escaped quote */
- X if (*str == '\\' && str[1] == quote)
- X ++str;
- X ++str;
- X }
- X
- X return (str);
- X}
- X
- X
- X/*
- X * tunquote - remove quotes from a string
- X */
- Xchar *tunquote(str)
- Xchar *str;
- X{
- X char *s;
- X char *d;
- X
- X d = s = str;
- X
- X while (*s)
- X {
- X while (*s && *s == '"')
- X ++s;
- X
- X while (*s && *s != '"')
- X *d++ = *s++;
- X }
- X
- X *d = '\0';
- X
- X return (str);
- X}
- X
- X
- X/*
- X * tsplit - split a string into two components, normally a directory
- X * path and a filename. If a pointer to a directory is
- X * supplied, a string is allocated to contain the directory.
- X * The filename is returned as a pointer into the supplied
- X * string.
- X */
- Xchar *tsplit(s, seps, dp)
- Xchar *s;
- Xchar *seps;
- Xchar **dp;
- X{
- X char *d; /* directory portion */
- X char *f; /* file portion */
- X
- X d = s;
- X
- X /* find the final separator */
- X while ((f = strpbrk(d, seps)) != NULL)
- X d = f + 1;
- X
- X /* back up to final component */
- X f = d;
- X
- X /* if we are still at the beginning, there was no Directory */
- X if (d == s || dp == NULL)
- X d = NULL;
- X else
- X {
- X int len;
- X
- X /*
- X * by the time we get here, d points to the final separator
- X * char. we can substitute a NULL for this sep-char. Thus,
- X * we don't need to add 1 in the following length
- X * calculation.
- X */
- X len = d - s;
- X
- X d = talloc(len);
- X d[--len] = '\0';
- X while (--len >= 0)
- X d[len] = s[len];
- X }
- X
- X if (dp != NULL)
- X *dp = d;
- X
- X return (f);
- X}
- X
- X
- X/*
- X * token - take an input string and return a token each call
- X * - default token delimiter characters are `isspace()'
- X * - separator chars are in addition to `isspace()'
- X * - text between quotes (" and ') is a single token
- X * - if requested, the separator char is returned
- X *
- X * called as s = token(string, seps, &schar);
- X * or s = token(string, NULL, NULL);
- X *
- X * followed by s = token(NULL, seps, NULL);
- X * or s = token(NULL, NULL, &schar);
- X *
- X * returns NULL when no more tokens are available
- X */
- Xchar *token(s, sep, schar)
- Xchar *s;
- Xchar *sep;
- Xchar *schar;
- X{
- X static char *olds = NULL;
- X
- X if (s)
- X olds = s; /* we are starting all over again */
- X
- X if (schar)
- X *schar = '\0';
- X
- X if (!olds || !*olds)
- X return (NULL); /* no tokens left */
- X
- X while (isspace(*olds) || (sep && strchr(sep, *olds)))
- X ++olds; /* skip leading spaces and sep's */
- X
- X if (*olds == NULL)
- X return (NULL); /* remainder is all separator's */
- X
- X s = olds;
- X
- X while (*olds)
- X {
- X if (isspace(*olds) || (sep && strchr(sep, *olds)))
- X {
- X if (schar)
- X *schar = *olds;
- X *olds++ = '\0'; /* delimit the token */
- X return (s);
- X }
- X else
- X if (*olds == '"' || *olds == '\'')
- X {
- X olds = tstrspan(olds);
- X if (*olds != '\0')
- X ++olds; /* didn't hit eos, so skip quote */
- X }
- X else
- X ++olds; /* otherwise, pass over char */
- X }
- X
- X olds = NULL;
- X return (s); /* return last token */
- X}
- X
- X
- X/*
- X * tokenize - chop a string up into an array of (char *)'s
- X */
- Xchar **tokenize(input)
- Xchar *input;
- X{
- X char **argv;
- X int argc = 0;
- X int alen;
- X
- X alen = 20; /* good initial guess */
- X argv = (char **) talloc((alen + 1) * sizeof(char *));
- X
- X input = token(input, NULL, NULL); /* use default separators */
- X while (input)
- X {
- X if (alen == argc)
- X argv = (char **) trealloc((char *) argv,
- X (alen <<= 1) * sizeof(char *));
- X argv[argc++] = input;
- X input = token(NULL, NULL, NULL);
- X }
- X
- X argv[argc] = NULL; /* mark end of array */
- X
- X return (argv);
- X}
- X
- X
- X/*
- X * tgets - read input, swallowing escaped newlines as necessary
- X */
- Xchar *tgets(fd)
- XFILE *fd;
- X{
- X static char *input = NULL;
- X static int inlen = 0;
- X char *ep;
- X int len;
- X
- X if (inlen == 0)
- X input = talloc(inlen = 162);
- X
- X input[inlen - 2] = '\n';
- X ep = input - 1;
- X while ((fgets(input, inlen, fd)) != NULL)
- X {
- X for (;;)
- X {
- X while (input[inlen - 2] != '\n' && input[inlen - 2] != '\0')
- X {
- X len = inlen;
- X input = trealloc(input, inlen <<= 1);
- X ep = &input[len - 2];
- X input[inlen - 2] = '\n';
- X fgets(ep + 1, len + 1, fd);
- X }
- X
- X while (*++ep);
- X *--ep = '\0';
- X do
- X {
- X --ep;
- X } while (ep >= input && isspace(*ep));
- X
- X if (ep > input && *ep == '\\' && *--ep != '\\')
- X fgets(ep + 1, inlen - (ep - input) - 1, fd);
- X else
- X break;
- X }
- X
- X return (input);
- X }
- X
- X inlen = 0;
- X tfree(input);
- X input = NULL;
- X
- X return (NULL);
- X}
- END_OF_FILE
- if test 5480 -ne `wc -c <'tstring.c'`; then
- echo shar: \"'tstring.c'\" unpacked with wrong size!
- fi
- # end of 'tstring.c'
- fi
- if test -f 'tstring.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tstring.h'\"
- else
- echo shar: Extracting \"'tstring.h'\" \(1310 characters\)
- sed "s/^X//" >'tstring.h' <<'END_OF_FILE'
- X/*
- X * tstring.h
- X *
- X * 88-10-01 v1.0 created by greg yachuk, placed in the public domain
- X * 88-10-06 v1.1 changed prerequisite list handling
- X * 88-11-11 v1.2 fixed some bugs and added environment variables
- X * 89-07-12 v1.3 stop appending shell commands, and flush output
- X * 89-08-01 v1.4 AB lots of new options and code
- X * 89-10-30 v1.5 -f -S -q options, took some changes from v1.4
- X * 90-04-18 v1.6 -b -- -W options, emulate <<, non-BSD cleanup
- X */
- X#define tnew(t) ((t *) talloc(sizeof(t)))
- X#define tfree(t) (free((char *) t))
- X
- X#define tstrcat(s,p) (strcat(strcpy(talloc(strlen(s)+strlen(p)+1),(s)),(p)))
- X#define tstrcpy(s) (strcpy(talloc(strlen(s)+1), (s)))
- X
- X#ifdef __STDC__
- Xextern char *talloc(int n);
- Xextern char *trealloc(char *s, int n);
- Xextern char *tstrncpy(char *s, int n);
- Xextern int terror(int n, char *s);
- Xextern char *tstrspan(char *str);
- Xextern char *tunquote(char *str);
- Xextern char *tsplit(char *s, char *seps, char **dp);
- Xextern char *token(char *s, char *sep, char *schar);
- Xextern char **tokenize(char *input);
- Xextern char *tgets(FILE * fd);
- X#else
- Xextern char *talloc();
- Xextern char *trealloc();
- Xextern char *tstrncpy();
- Xextern int terror();
- Xextern char *tstrspan();
- Xextern char *tunquote();
- Xextern char *tsplit();
- Xextern char *token();
- Xextern char **tokenize();
- Xextern char *tgets();
- X#endif
- END_OF_FILE
- if test 1310 -ne `wc -c <'tstring.h'`; then
- echo shar: \"'tstring.h'\" unpacked with wrong size!
- fi
- # end of 'tstring.h'
- fi
- echo shar: End of archive 2 \(of 2\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-